package pl.kosmowska.ewelina.server.dao;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;

import net.sf.flatpack.DataSet;
import net.sf.flatpack.DefaultParserFactory;
import net.sf.flatpack.Parser;
import pl.kosmowska.ewelina.server.jdo.StockData;

public class StockDataDAO extends JdoDAOImpl<StockData> {

	private static final Logger log = Logger.getLogger(StockDataDAO.class
			.getName());

	private final static String defaultUrl = "http://xml.wyborcza.biz/exchangeTableExport.servlet?sessionDate="+"yyyy-MM-dd"+"&exportType=CSV&market=GPW&instrumentType=SHARE_PP_PDA&indexName=&futureGroup=ALL&qType=ALL";


	public  StockData findStockData(String id) {
		return (StockData) findById(id);
	}

	public List<String> getStockNames(){
		List<String> nameList = new ArrayList<String>();
		String pricesTable = getLastNotEmptyPricesTable();

		//Obtain the proper parser for your needs
		Parser parser = DefaultParserFactory.getInstance().newDelimitedParser(
				new StringReader(pricesTable),  //txt file to parse
				';', //delimiter
				'"'); //text qualifier

		//obtain DataSet
		DataSet ds = parser.parse();

		while (ds.next()){ //loop through file
			nameList.add ( ds.getString("Nazwa") );
		}

		return nameList;
	}



	public  void updateCurrentValue (StockData stockData) {

		try{
			String pricesTable = getLastNotEmptyPricesTable();

			//Obtain the proper parser for your needs
			Parser parser = DefaultParserFactory.getInstance().newDelimitedParser(
					new StringReader(pricesTable),  //txt file to parse
					';', //delimiter
					'"'); //text qualifier

			//obtain DataSet
			DataSet ds = parser.parse();

			boolean success=false;
			while (ds.next()){ //loop through file
				if (ds.getString("Nazwa").equals(stockData.getName())){
					success=true;
					break;
				}
			}
			if(!success){
				return;
			}

			String valueString =ds.getString("Kurs");
			Number num = parseNumber(valueString);
			float valueFloat = num.floatValue();
			stockData.setCurrentValue(valueFloat); 
			stockData.setPercentage( stockData.getCurrentValue()/stockData.getStartValue()*100 -100);
			stockData.setTotalValue(stockData.getCurrentValue()*stockData.getStockNumber());

		} catch (ParseException e) {
			e.printStackTrace();
		}
	}




	public  List<StockData> findStockDataByUser() {
		Long uid = UserDataDAO.getLoggedInUserId();

		String qfilter = "userId==" + uid + "";

		PersistenceManager pm = getPersistenceManager();
		try {
			javax.jdo.Query query = pm.newQuery("select from " + StockData.class.getName());
			query.setFilter(qfilter);
			List<StockData> list = (List<StockData>) query.execute();
			List<StockData> r = (List<StockData>) pm.detachCopyAll(list);
			if(r!=null && r.size()!=0)
				updateCurrentValue(r);

			return r;
		} catch (Exception e) {
			log.log(Level.SEVERE, "Error: StockData.findStockDataByUser(): qfilter=" + qfilter, e);
			e.printStackTrace();
		} finally {
			pm.close();
		}
		return null;
	}


	private  void updateCurrentValue(List<StockData> list) {

		try{

			String pricesTable = getLastNotEmptyPricesTable();
			if(pricesTable==null)
				return;
			//Obtain the proper parser for your needs
			Parser parser = DefaultParserFactory.getInstance().newDelimitedParser(
					new StringReader(pricesTable),  //txt file to parse
					';', //delimiter
					'"'); //text qualifier

			DataSet ds = parser.parse();
			while(ds.next()) {
				for(StockData stockData: list){
					if(ds.getString("Nazwa").equals(stockData.getName())){
						String valueString =ds.getString("Kurs");
						float newValue =parseNumber(valueString); 
						float newTotalValue =(newValue* stockData.getStockNumber());
						float newPercentageValue =(newValue/stockData.getStartValue()*100-100);
						stockData.setCurrentValue(newValue);
						stockData.setPercentage(newPercentageValue);
						stockData.setTotalValue(newTotalValue);
					}
				}
			}

			for(StockData stockData: list){
				persist(stockData);
			}

		} catch (ParseException e) {
			log.log(Level.SEVERE, "Parse exception" , e);
			e.printStackTrace();
		}


	}

	private float parseNumber(String valueString) throws ParseException {
		DecimalFormatSymbols sym = new DecimalFormatSymbols();
		sym.setDecimalSeparator(',');
		DecimalFormat form = new DecimalFormat("");
		form.setDecimalFormatSymbols(sym);
		Number num = form.parse(valueString);
		return num.floatValue();
	}

	private String getLastNotEmptyPricesTable(){
		//last week
		String lastPricesTable =null;
		Date currentDate = new Date();
		for (int i=0; i<7;i++){
			lastPricesTable = getStockPricesTable(currentDate);
			if((lastPricesTable==null)||checkIfPricesTableEmpty(lastPricesTable)){
				currentDate = getPriorDay(currentDate);
				continue;
			}else{
				break;
			}

		}
		return lastPricesTable;
	}

	private boolean checkIfPricesTableEmpty(String lastPricesTable) {
		return !lastPricesTable.contains("0");
	}

	private String getStockPricesTable(Date date){
		String url = findURL(date);
		try{
			InputStream is= getFileFromUrl(url);
			String file = convertStreamToString(is);
			String alteredFile=removeSemiColonsAtTheEnd(file);
			return alteredFile;
		}catch(MalformedURLException e){
			log.log(Level.SEVERE, "Wrong URL exception: " + url, e);
			e.printStackTrace();			
		}catch (IOException e) {
			log.log(Level.SEVERE, "IO exception: " + url, e);
			e.printStackTrace();
		}
		return null;

	}

	private  InputStream getFileFromUrl(String url) throws MalformedURLException, IOException {
		URL myFileUrl = new URL(url);
		HttpURLConnection conn= (HttpURLConnection)myFileUrl.openConnection();
		conn.setDoInput(true);
		conn.connect();
		InputStream is = conn.getInputStream();
		return is;
	}

	public  String convertStreamToString(InputStream is) throws IOException  {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();
		String line = null;
		while ((line = reader.readLine()) != null) {
			sb.append(line + "\n");
		}
		is.close();
		return sb.toString();      
	}

	private  String removeSemiColonsAtTheEnd(String file) {
		Scanner scanner = new Scanner(file);
		List<String>lines = new ArrayList<String>();
		while (scanner.hasNextLine()) {
			String line = scanner.nextLine();
			line = line.substring(0, line.length()- 1);
			lines.add(line);
			// process the line
		}
		String alteredFile="";
		for(String line: lines){
			alteredFile+=line+"\n";
		}
		return alteredFile;
	}


	private  String findURL(Date date) {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); 
		String stringDate = formatter.format(date);
		String url = defaultUrl.replaceFirst("yyyy-MM-dd", stringDate);
		return url;
	}

	private Date getPriorDay(Date date){
		int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
		return new Date(date.getTime() - MILLIS_IN_DAY);
	}

	public StockData persist(StockData stockData) {
		return (StockData) persistEntity(stockData);
	}



}